<?php
/**
 *
 */
namespace App\Func;

use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\File\UploadedFile;
Class UploadFile
{
    private static $_instance = null;

    /**
     * Storage instance.
     * @var \Illuminate\Contracts\Filesystem\Filesystem|string
     */
    protected $storage = '';

    protected $imageType = ['jpg', 'jpeg', 'gif', 'bmp', 'png'];

    protected $fileTypes = [
        'image'      => 'png|jpg|jpeg|tmp|gif',
        'word'       => 'doc|docx',
        'excel'      => 'xls|xlsx|csv',
        'powerpoint' => 'ppt|pptx',
        'pdf'        => 'pdf',
        'code'       => 'php|js|java|python|ruby|go|c|cpp|sql|m|h|json|html|aspx',
        'archive'    => 'zip|tar\.gz|rar|rpm',
        'txt'        => 'txt|pac|log|md',
        'audio'      => 'mp3|wav|flac|3pg|aa|aac|ape|au|m4a|mpc|ogg',
        'video'      => 'mkv|rmvb|flv|mp4|avi|wmv|rm|asf|mpeg',
    ];

    public static function getInit($disk = ''){
        if(!is_object(self::$_instance)){
            self::$_instance = new self($disk);
        }
        return self::$_instance;
    }

    public function __construct($disk = '')
    {
        $this->storage = Storage::disk($disk ?: config('admin.upload.disk'));
    }

    /**
     * Upload file and delete original file.
     * @param UploadedFile $file
     * @param string       $dir
     * @param bool         $flag
     * @param string       $name
     * @return mixed
     */
    public function upload(UploadedFile $file, $dir = '', $flag = true, $name = '')
    {
        $uploadDir = $this->getDirectory($file->getClientOriginalExtension(),$dir);
        return $this->storage->putFileAs($uploadDir, $file, $this->renameIfExists($file,$uploadDir,$name,$flag));
    }

    /**
     * Get directory for store file.
     * @param $ext
     * @param string $dir
     * @return \Illuminate\Config\Repository|mixed
     */
    protected function getDirectory($ext,$dir = '')
    {
        return $dir ?: $this->defaultDirectory($ext);
    }

    /**
     * default directory
     * @param $ext
     * @return \Illuminate\Config\Repository|mixed
     */
    protected function defaultDirectory($ext){
        return in_array($ext,$this->imageType) ? config('admin.upload.directory.image') : config('admin.upload.directory.file');
    }

    /**
     * If name already exists, rename it.
     * @param UploadedFile $file
     * @param              $uploadDir
     * @param string       $name
     * @param bool         $flag
     * @return null|string
     */
    protected function renameIfExists(UploadedFile $file, $uploadDir, $name = '',$flag = true)
    {
        $uploadName = $name ?: $file->getClientOriginalName();
        if ($flag && $this->storage->exists("{$uploadDir}/{$uploadName}")) {
            return '('.time().').'.$uploadName;
        }else{
            return $uploadName;
        }
    }

    /**
     * Get file visit url.
     * @param $path
     * @return mixed
     */
    public function objectUrl($path)
    {
        if (url()->isValidUrl($path)) {
            return $path;
        }
        return $this->storage->url($path);
    }

    /**
     * Destroy files.
     * @param UploadedFile $file
     */
    public function destroy(UploadedFile $file)
    {
        if ($this->storage->exists($file)) {
            $this->storage->delete($file);
        }
    }

    public function initialPreviewUploadFile($value){
        $files = $value ? json_decode($value,true) : [];
        return array_map([$this, 'objectUrl'], $files);
    }

    public function initialPreviewConfigUploadFile($value){
        $files = $value ? json_decode($value,true) : [];
        $config = [];
        foreach ($files as $index => $file) {
            $config[] = [
                'caption' => basename($file),
                'key'     => $index,
            ];
        }
        return $config;
    }

    public function delFile($file){
        if ($this->storage->exists($file)) {
            return $this->storage->delete($file);
        }else{
            return true;
        }
    }

    public function getFileIcon($file = '')
    {
        $extension = File::extension($file);
        foreach ($this->fileTypes as $type => $regex) {
            if (preg_match("/^($regex)$/i", $extension) !== 0) {
                return "fa-file-{$type}-o";
            }
        }
        return 'fa-file-o';
    }
}
